package com.dodoke.provider;

import com.dodoke.common.constant.UserConstants;
import com.dodoke.common.utils.ServletUtils;
import com.dodoke.common.utils.ip.IpUtils;
import com.dodoke.domain.WxUser;
import com.dodoke.service.IWxUserService;
import com.dodoke.token.WechatAuthenticationToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.SpringSecurityMessageSource;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.util.Assert;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * 微信认证策略入口
 */
public class WechatAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private IWxUserService wxUserService;

    // 上下文中的 userDetailsService
    private UserDetailsService userDetailsService;
    private MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();


    @Override
    public Authentication authenticate(Authentication authentication) {
        Assert.isInstanceOf(WechatAuthenticationToken.class, authentication,
                messages.getMessage(
                        "SmsAuthenticationProvider.onlySupports",
                        "Only SmsAuthenticationToken is supported"));

        WechatAuthenticationToken authenticationToken = (WechatAuthenticationToken) authentication;
        //将验证信息保存在SecurityContext以供UserDetailsService进行验证
        SecurityContext context = SecurityContextHolder.getContext();
        context.setAuthentication(authenticationToken);
        WxUser wxUser = (WxUser) authenticationToken.getPrincipal();
        if (wxUser == null) {
            throw new InternalAuthenticationServiceException("can't obtain user info ");
        }
        //进行验证以及获取用户信息
        UserDetails user = userDetailsService.loadUserByUsername(wxUser.getOpenid());
        HttpServletRequest request = ServletUtils.getRequest();
        String ipAddr = IpUtils.getIpAddr(request);
        Date date = new Date();
        wxUser.setLoginIp(ipAddr);
        wxUser.setLoginDate(date);
        wxUser.setUpdateTime(date);
        wxUser.setUpdateBy(UserConstants.ADMIN);
        // 通过openId没有找到Wxuser对象
        if (user == null) {
            // 新增数据
            wxUser.setCreateTime(date);
            wxUser.setCreateBy(UserConstants.ADMIN);
            wxUser.setRemark(UserConstants.NORMAL);
            wxUserService.insertWxUser(wxUser);
        }else {
            // 更新数据库数据
            wxUserService.updateWxUser(wxUser);
        }
        return new WechatAuthenticationToken(user,"");
    }

    @Override
    public boolean supports(Class<?> authentication) {
        // 判断 authentication 是不是 SmsCodeAuthenticationToken 的子类或子接口
        return (WechatAuthenticationToken.class.isAssignableFrom(authentication));
    }

    public void setUserDetailsService(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    public UserDetailsService getUserDetailsService() {
        return userDetailsService;
    }
}
